package edu.fudan.jwxt.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.fudan.jwxt.Exception.ServiceException;
import edu.fudan.jwxt.common.Constants;
import edu.fudan.jwxt.common.RoleConstant;
import edu.fudan.jwxt.dao.CollegeDao;
import edu.fudan.jwxt.dao.CourseDao;
import edu.fudan.jwxt.dao.MajorDao;
import edu.fudan.jwxt.dao.UserDao;
import edu.fudan.jwxt.dto.PasswordDto;
import edu.fudan.jwxt.dto.UserDto;
import edu.fudan.jwxt.entity.College;
import edu.fudan.jwxt.entity.Major;
import edu.fudan.jwxt.entity.User;
import edu.fudan.jwxt.service.UserService;
import edu.fudan.jwxt.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;


@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private MajorDao majorDao;

    @Autowired
    private CollegeDao collegeDao;

    @Autowired
    private CourseDao courseDao;


    @Override
    public UserDto login(UserDto userDto) {
        String uid = userDto.getUid();
        String password = userDto.getPassword();
        //创建查询操作类
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(i->i.eq(User::getUid,uid).eq(User::getPassword,password));

        User user = userDao.selectOne(queryWrapper);

        if (user == null){
            throw new ServiceException(Constants.CODE_600, "ID不存在或密码错误");
        }else if(Objects.equals(user.getStatus(), RoleConstant.INVALID_STATUS))
            throw new ServiceException(Constants.CODE_600, "账号已被注销");


        //属性提取
        BeanUtil.copyProperties(user,userDto,true);
        // 设置token
        String token = TokenUtils.genToken(user.getUid(), user.getPassword());
        userDto.setToken(token);
        JwtInterceptor.addUserToken(uid,token);

        //设置状态
        user.setStatus(RoleConstant.NORMAL_STATUS);
        LambdaQueryWrapper<User> q = new LambdaQueryWrapper<>();
        q.and(i->i.eq(User::getUid,uid));
        userDao.update(user,q);

        return userDto;
    }

    @Override
    public List<User> list(){
        List<User> users = userDao.selectList(null);
        for (User user : users){
            String collegeName = collegeDao.selectById(user.getCollegeId()).getName();
            String majorName = majorDao.selectById(user.getMajorId()).getMajorName();
            user.setCollegeName(collegeName);
            user.setMajorName(majorName);
        }

        return users;
    }

    @Override
    public User getById(Serializable id){
        User user = userDao.selectById(id);
        if (user != null){
            String collegeName = collegeDao.selectById(user.getCollegeId()).getName();
            String majorName = majorDao.selectById(user.getMajorId()).getMajorName();
            user.setCollegeName(collegeName);
            user.setMajorName(majorName);
        }
        return user;
    }

    @Override
    public String getNameById(Serializable id){
        User user=getById(id);
        return user.getName();
    }

    @Override
    public boolean updatePassword(PasswordDto passwordDto) {
        String uid = passwordDto.getUid();
        String oldPassword = passwordDto.getOldPassword();
        String newPassword = passwordDto.getNewPassword();
        //密码加密处理
        String finalOldPassword  = SecureUtil.sha256(oldPassword);

        //获取当前用户
        User currentUser = TokenUtils.getCurrentUser();


        //创建查询操作类
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.and(i->i.eq(User::getUid,uid).eq(User::getPassword, finalOldPassword));

        User user = userDao.selectOne(queryWrapper);

        if (user == null && !Objects.equals(currentUser.getRole(), RoleConstant.ADMIN)){
            throw new ServiceException(Constants.CODE_600, "原密码错误");
        }

        //密码格式检查
        if(!UserFormat.IsPassWord(newPassword)){
            throw new ServiceException(Constants.CODE_600, "密码格式错误");
        }

        //新密码加密处理
        newPassword = SecureUtil.sha256(newPassword);

        userDao.updatePassword(uid,newPassword);
        return true;
    }



    //对save方法进行重载，抛出自定义异常类
    @Override
    public boolean save(User user){
        User flag = userDao.selectById(user.getUid());
        if (flag != null){
            throw new ServiceException(Constants.CODE_600, "ID已存在");
        }

        //格式检查
        if(!UserFormat.IsRole(user.getRole()))
            throw new ServiceException(Constants.CODE_600, "用户身份格式错误");
        if(!UserFormat.IsUID(user.getUid()))
            throw new ServiceException(Constants.CODE_600, "学工号格式错误");
        if(!UserFormat.IsName(user.getName()))
            throw new ServiceException(Constants.CODE_600, "姓名格式错误");
        if(!UserFormat.IsMailBox(user.getEmail()))
            throw new ServiceException(Constants.CODE_600, "邮箱格式错误");
        if(!UserFormat.IsPhoneNum(user.getPhone()))
            throw new ServiceException(Constants.CODE_600, "电话号码格式错误");
        if(!UserFormat.IsIdCardNum(user.getIdentityId()))
            throw new ServiceException(Constants.CODE_600, "身份证号格式错误");

        //检查身份证号是否已注册
        User u= userDao.selectByIdentityId(user.getIdentityId());
        if(u != null)
            throw new ServiceException(Constants.CODE_600,"身份证号已被注册");

        //学院专业信息检查
        Map<String, Integer> map = MajorCollegeCheck(user);
        user.setCollegeId(map.get("collegeId"));
        user.setMajorId(map.get("majorId"));

        //生成初始密码并加密
        String password = GeneratePassword.genPassword();
        password = SecureUtil.sha256(password);
        user.setPassword(password);

        //设置初始状态
        user.setStatus(RoleConstant.INITIAL_STATUS);

        userDao.insert(user);
        return true;
    }

    @Override
    public Map<String, Object> saveList(List<User> users) {
        int sucsess = 0,fail = 0,count = 0;
        Map<String, Object> map = new HashMap<>();
        List<String> errmsg = new ArrayList<>();
        for(User user : users){
            count++;
            try {

                save(user);
            }catch (ServiceException e){
                fail ++;
                errmsg.add("第" + count + "行：" + e.getMessage());
            }
            catch (Exception e){
                fail++;
            }
        }
        sucsess = count - fail;
        map.put("success",sucsess);
        map.put("fail", fail);
        map.put("count", count);
        map.put("errmsg",errmsg);
        return map;
    }

    //对update方法进行重载,进行数据格式检查
    @Override
    public boolean updateById(User user){
        //对用户个人信息的格式进行判断
        if(!UserFormat.IsMailBox(user.getEmail()))
            throw new ServiceException(Constants.CODE_600, "邮箱格式错误");
        if(!UserFormat.IsRole(user.getRole()))
            throw new ServiceException(Constants.CODE_600, "用户身份格式错误");
        if(!UserFormat.IsName(user.getName()))
            throw new ServiceException(Constants.CODE_600, "姓名格式错误");
        if(!UserFormat.IsPhoneNum(user.getPhone()))
            throw new ServiceException(Constants.CODE_600, "电话号码格式错误");
        if(!UserFormat.StatusCheck(user.getStatus()))
            throw new ServiceException(Constants.CODE_600, "状态格式错误");
        if(collegeDao.selectById(user.getCollegeId()) == null)
            throw new ServiceException(Constants.CODE_600, "学院不存在");
        if(majorDao.selectById(user.getMajorId()) == null)
            throw new ServiceException(Constants.CODE_600, "专业不存在");

        //当前用户身份检查
        User currentUser = TokenUtils.getCurrentUser();
        assert currentUser != null;
        String role = currentUser.getRole();
        if(Objects.equals(role, RoleConstant.ADMIN)){
            //学院专业信息检查
            user.setCollegeName(collegeDao.selectById(user.getCollegeId()).getName());
            user.setMajorName(majorDao.selectById(user.getMajorId()).getMajorName());
            Map<String, Integer> map = MajorCollegeCheck(user);
            user.setCollegeId(map.get("collegeId"));
            user.setMajorId(map.get("majorId"));
            userDao.updateUserByAdmin(user);
        }
        else {
            userDao.updateUserByPerson(user);
        }
        return true;
    }

    private Map<String,Integer> MajorCollegeCheck(User user){
        String majorName = user.getMajorName();
        String collegeName = user.getCollegeName();

        if(majorName == null)
            throw new ServiceException(Constants.CODE_600, "专业名称不能为空");
        if(collegeName == null)
            throw new ServiceException(Constants.CODE_600, "学院名称不能为空");
        //检查学院是否存在
        LambdaQueryWrapper<College> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(College::getName,collegeName);
        College college = collegeDao.selectOne(queryWrapper);
        if(college == null)
            throw new ServiceException(Constants.CODE_600, "该学院不存在");
        //检查专业是否存在
        LambdaQueryWrapper<Major> q = new LambdaQueryWrapper<>();
        q.eq(Major::getMajorName,majorName);
        Major major = majorDao.selectOne(q);
        //找到major对应的学院名
        if(major == null)
            throw new ServiceException(Constants.CODE_600, "专业不存在");

        String collegeNameOfMajor = collegeDao.selectById(major.getCollegeId()).getName();
        if(!Objects.equals(collegeNameOfMajor, user.getCollegeName()))
            throw new ServiceException(Constants.CODE_600, "学院和专业不匹配");

        int collegeId = college.getId();
        int majorId = major.getId();
        Map<String, Integer> map = new HashMap<>();
        map.put("collegeId",collegeId);
        map.put("majorId",majorId);

        return map;
    }

    public boolean updateStatus(User user){
        String uid = user.getUid();
        User u = userDao.selectById(uid);
        if(u == null)
            return false;

        boolean flag = UserFormat.StatusCheck(user.getStatus());
        if(!flag)
            throw new ServiceException(Constants.CODE_600, "状态格式错误");

        userDao.updateStatus(user);
        return true;
    }
    /*
    @Override
    public boolean removeById(Serializable id) {
        if(Objects.equals(userDao.selectById(id).getRole(), RoleConstant.TeacherStr)) {
            LambdaQueryWrapper<Course> q1 = new LambdaQueryWrapper<>();
            q1.eq(Course::getTeacherId, id);

            long courseCount = courseDao.selectCount(q1);
            if(courseCount != 0)
                throw new ServiceException(Constants.CODE_600,"该教师有开设课程，请先删除");
        }


        return super.removeById(id);
    }
     */

    @Override
    public String getNameByUid(String uid) {
        User user = getById(uid);
        return user.getName();
    }


}
